package cs236369.hw5.rest;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.log4j.Logger;

import cs236369.hw5.axis2.client.SearchWSClient;
import cs236369.hw5.db.DbHandler;
import cs236369.hw5.db.DbHandlerImp;
import cs236369.hw5.db.beans.DbEvent;
import cs236369.hw5.db.beans.DbMessage;
import cs236369.hw5.db.beans.DbUser;
import cs236369.hw5.db.types.DbMsgType;
import cs236369.hw5.rest.beans.EventBean;
import cs236369.hw5.rest.beans.MessageBean;
import cs236369.hw5.rest.beans.SearchServiceBean;

//@Consumes({"application/xml", "application/json"})
@Path("/user-api")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class UserApi
{

	private DbHandler db = new DbHandlerImp();

	/**
	 * delete the msg with id, which is associated to the user
	 * 
	 * @param req
	 * @param res
	 * @param id
	 */
	@DELETE
	@Path("/message/delete/{id}")
	public void deleteMessage(@Context HttpServletRequest req, @Context HttpServletResponse res,
	    @PathParam("id") Long id)
	{
		Logger l = Logger.getLogger(getClass());
		String username = req.getUserPrincipal().getName();
		l.info("adding new msg for: " + username);
		db.deleteUserMessage(username, id);

	}

	/**
	 * 
	 * @param msg is the msg bean to add
	 * @param req is the request resource, username will be get from there
	 * @param res is the respone, in case there is an error that needs to be sent...
	 * @return void,
	 */
	@PUT
	@Path("/message/post/add")
	public void addMessage(@Context HttpServletRequest req, @Context HttpServletResponse res, MessageBean msg)
	{
		Logger l = Logger.getLogger(getClass());
		try
		{
			if (null == msg.getContent() || null == msg.getPoint())
			{
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
				return;
			}

			String username = req.getUserPrincipal().getName();
			l.info("adding new msg for: " + username);
			DbMessage dbmsg = new DbMessage(DbMsgType.post, msg.getContent(), msg.getPoint().getX(), msg.getPoint()
			    .getY());
			dbmsg.setUser(new DbUser(username));
			try
			{
				db.save(dbmsg);
			}
			catch (Exception e)
			{
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
			}
		}
		catch (IOException e1)
		{
			l.error("can't send error response to user", e1);
		}
	}

	/**
	 * adds an event
	 * 
	 * @param event
	 * @return
	 */
	@PUT
	@Path("/message/event/add")
	public void addEvent(@Context HttpServletRequest req, @Context HttpServletResponse res, EventBean event)
	{
		Logger l = Logger.getLogger(getClass());
		try
		{
			if (null == event.getDay() || null == event.getDay() || null == event.getYear() || //
			    null == event.getMsg() || null == event.getMsg().getContent() || null == event.getMsg().getPoint())
			{
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
				return;
			}
			String username = req.getUserPrincipal().getName();
			l.info("adding new msg for: " + username);
			DbMessage dbmsg = new DbMessage(DbMsgType.event, event.getMsg().getContent(), //
			    event.getMsg().getPoint().getX(), event.getMsg().getPoint().getY());
			dbmsg.setUser(new DbUser(username));
			int year = 0;
			int month = 0;
			int day = 0;
			try
			{
				year = Integer.parseInt(event.getYear());
				month = Integer.parseInt(event.getMonth());
				day = Integer.parseInt(event.getDay());
			}
			catch (Exception e)
			{
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
			}
			Calendar cal = GregorianCalendar.getInstance();
			cal.set(1900 + year, month, day);
			Date date = cal.getTime();

			dbmsg.addEvent(new DbEvent(dbmsg, event.getCapacity(), date));
			try
			{
				db.save(dbmsg);
			}
			catch (Exception e)
			{
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
			}
		}
		catch (Exception e1)
		{
			l.error("can't send error response to user", e1);
		}
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	@GET
	@Path("/message/event/register")
	public void registerToEvent(@Context HttpServletRequest req, @Context HttpServletResponse res,
	    @QueryParam("id") long id)
	{
		String username = req.getUserPrincipal().getName();
		db.registerEvent(username, id);
	}

	@GET
	@Path("/message/event/unregister")
	public void unregisterFromEvent(@Context HttpServletRequest req, @Context HttpServletResponse res,
	    @QueryParam("id") long id)
	{
		String username = req.getUserPrincipal().getName();
		db.unRegisterEvent(username, id);
	}

	@DELETE
	@Path("/delete")
	public void deleteMyself(@Context HttpServletRequest req)
	{
		String username = req.getUserPrincipal().getName();
		db.deleteUser(username);
		req.getSession().invalidate();
	}

	/**
	 * yellowPages service
	 * 
	 * @param id
	 * @return
	 */
	@POST
	@Path("/service")
	public String[] searchService(@Context HttpServletResponse res, SearchServiceBean search)
	{
		Logger logger = Logger.getLogger(getClass());
		try
		{
			if (null == search.getUrl() || search.getUrl().isEmpty() //
			    || null == search.getMethod() || search.getMethod().isEmpty())
			{
				logger.info("url was empty");
				int status = HttpStatus.SC_BAD_REQUEST;
				res.sendError(status, HttpStatus.getStatusText(status));
				return null;
			}
			try
			{
				SearchWSClient client = new SearchWSClient(search.getUrl());
				String[] result = null;
				if (search.getMethod().equals("search_locations"))
				{
					result = client.searchLocal(search.getLat(), search.getLng(), search.getRadius());
				}
				else if (search.getMethod().equals("search_keywords"))
				{
					String[] k = search.getKeywords().split(" ");
					result = client.searchKeywords(k);
				}
				logger.info("returning: " + result.toString());
				return (null != result) ? result : new String[0];
			}
			catch (Exception e)
			{
				logger.error("service is down", e);
				int status = HttpStatus.SC_METHOD_FAILURE;
				res.sendError(status, HttpStatus.getStatusText(status));
				return null;
			}
		}
		catch (Exception e)
		{
			logger.error("can't send error", e);
			return null;
		}

	}
}
